/*
 * Copyright (C) 2021 Baidu, Inc. All Rights Reserved.
 */
package com.chukun.rpc.protocol.codec;

import com.chukun.rpc.protocol.protocol.MessageHeader;
import com.chukun.rpc.protocol.protocol.TinyRpcProtocol;
import com.chukun.rpc.protocol.serialization.SerializationFactory;
import com.chukun.rpc.protocol.serialization.TinyRpcSerialization;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import lombok.extern.slf4j.Slf4j;

/**
 * <p>rpc框架编码器<p/>
 *
 * @author chukun
 * @version 1.0
 * @since 1.0-SNAPSHOT
 */
@Slf4j
public class TinyRpcEncoder extends MessageToByteEncoder<TinyRpcProtocol<Object>> {

    /*
       +---------------------------------------------------------------+
       | 魔数 2byte | 协议版本号 1byte | 序列化算法 1byte | 报文类型 1byte  |
       +---------------------------------------------------------------+
       | 状态 1byte |        消息 ID 8byte     |      数据长度 4byte     |
       +---------------------------------------------------------------+
       |                   数据内容 （长度不定）                          |
       +---------------------------------------------------------------+
   */

    @Override
    protected void encode(ChannelHandlerContext channelHandlerContext, TinyRpcProtocol<Object> message,
                          ByteBuf byteBuf) throws Exception {
        log.info("TinyRpcEncoder encode data arrival......");
        MessageHeader header = message.getHeader();
        byteBuf.writeShort(header.getMagic());
        byteBuf.writeByte(header.getVersion());
        byteBuf.writeByte(header.getSerialization());
        byteBuf.writeByte(header.getMessageType());
        byteBuf.writeByte(header.getStatus());
        byteBuf.writeLong(header.getRequestId());

        TinyRpcSerialization serialization =
                SerializationFactory.getInstance().getSerializationByType(header.getSerialization());
        byte[] data = serialization.serialize(message.getBody());
        byteBuf.writeInt(data.length);
        byteBuf.writeBytes(data);
    }
}
